package com.baiyue.utils;

import com.baiyue.exception.GlobalException;
import com.baiyue.result.CodeMsg;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.ContentDisposition;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.*;

/**
 * @author 伍波
 * @date 2023/6/28 19:59
 */
public class CsvUtils {
    private static final Logger logger = LoggerFactory.getLogger(CsvUtils.class);

    public static List<List<String>> readColumnByHeader(InputStream fileInputStream, List<String> headerNames) throws IOException {
        List<List<String>> columnDataList = new ArrayList<>();

        try (InputStreamReader reader = new InputStreamReader(fileInputStream);
             BufferedReader bufferedReader = new BufferedReader(reader)) {
            // 读取第一行获取表头信息
            String line = bufferedReader.readLine();
            String[] header = line.split(",");

            // 查找指定表头的索引
            int[] columnIndices = new int[headerNames.size()];
            for (int i = 0; i < header.length; i++) {
                String columnName = header[i];
                for (int j = 0; j < headerNames.size(); j++) {
                    if (columnName.equals(headerNames.get(j))) {
                        columnIndices[j] = i;
                        break;
                    }
                }
            }

            // 逐行读取数据并获取指定列的值
            while ((line = bufferedReader.readLine()) != null) {
                String[] data = line.split(",");

                List<String> columnData = new ArrayList<>();
                for (int columnIndex : columnIndices) {
                    if (data.length > columnIndex) {
                        String columnValue = data[columnIndex];
                        columnData.add(columnValue);
                    }
                }

                columnDataList.add(columnData);
            }
        }

        return columnDataList;
    }

    public static void writeDataToCsv(String csvFilePath, List<String> headers, List<List<String>> data) {
        // 写入表头
        writeRow(csvFilePath, headers);

        // 写入数据行
        for (List<String> rowData : data) {
            writeRow(csvFilePath, rowData);
        }

        System.out.println("CSV 文件写入完成！");
    }

    private static void writeRow(String csvFilePath, List<String> rowData) {
        try (FileWriter writer = new FileWriter(csvFilePath, true)) {
            boolean isFirstItem = true;
            for (String item : rowData) {
                if (!isFirstItem) {
                    writer.append(",");
                }
                writer.append(item);
                isFirstItem = false;
            }
            writer.append("\n");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 读取Excel文件内容
     * @param file excel文件
     * @param headers 需要读取的表头数组
     * @return 返回数据列表
     * @throws IOException 文件读取异常抛出
     */
    public static List<List<String>> read(MultipartFile file, String[] headers) throws IOException {
        List<List<String>> result = new ArrayList<>();
        Workbook workbook = null;
        try{
             workbook = WorkbookFactory.create(file.getInputStream());
            // 假设只读取第一个 sheet
            Sheet sheet = workbook.getSheetAt(0);

            // 获取表头行
            Row headerRow = sheet.getRow(0);

            // 构建表头列索引的映射关系
            Map<String, Integer> headerIndexMap = new HashMap<>();
            for (int columnIndex = 0; columnIndex < headerRow.getLastCellNum(); columnIndex++) {
                Cell cell = headerRow.getCell(columnIndex);
                String header = cell.getStringCellValue().trim();
                if (!header.isEmpty()) {
                    headerIndexMap.put(header, columnIndex);
                }
            }

            // 根据传入的表头获取列数据
            List<Integer> columnIndexList = new ArrayList<>();
            for (String header : headers) {
                Integer index = headerIndexMap.get(header);
                if (index != null) {
                    columnIndexList.add(index);
                }
            }

            // 读取数据行
            for (int rowIndex = 1; rowIndex <= sheet.getLastRowNum(); rowIndex++) {
                Row dataRow = sheet.getRow(rowIndex);
                List<String> rowData = new ArrayList<>();
                for (Integer columnIndex : columnIndexList) {
                    Cell cell = dataRow.getCell(columnIndex);
                    if (cell != null) {
                        cell.setCellType(CellType.STRING);
                        String value = cell.getStringCellValue().trim();
                        rowData.add(value);
                    } else {
                        rowData.add("");
                    }
                }
                result.add(rowData);
            }

            return result;
        }finally {
            if(workbook != null){
                workbook.close();
            }
        }
    }

    /**
     * 下载模板文件
     * @param inFileName
     * @param outFileName
     * @return
     */
    public ResponseEntity<byte[]> downloadExcel(String inFileName, String outFileName) throws Exception {
        InputStream inputStream = null;
        BufferedInputStream bufferedInputStream = null;
        try {
            inputStream = getClass().getResourceAsStream("/fileTemplate/" + inFileName);
            bufferedInputStream = new BufferedInputStream(inputStream);

            byte[] data = new byte[bufferedInputStream.available()];
            bufferedInputStream.read(data);

            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);

            ContentDisposition contentDisposition = ContentDisposition.builder("attachment")
                    .filename(outFileName, StandardCharsets.UTF_8)
                    .build();

            headers.setContentDisposition(contentDisposition);

            return ResponseEntity
                    .ok()
                    .headers(headers)
                    .body(data);
        } finally {
            if (bufferedInputStream != null) {
                bufferedInputStream.close();
            }
            if (inputStream != null) {
                inputStream.close();
            }
        }
    }
}
